package com.nowcoder.community.service.impl;

import com.nowcoder.community.dao.elasticsearch.DiscussPostRepository;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.ElasticsearchService;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * Elasticsearch业务层实现
 * @author 花木凋零成兰
 * @date 2024/3/26 16:22
 */
@Service
public class ElasticsearchServiceImpl implements ElasticsearchService {

    @Resource
    private DiscussPostRepository discussPostRepository;

    @Resource
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 保存帖子
     * @param discussPost 帖子实例
     */
    public void saveDiscussPost(DiscussPost discussPost) {
        discussPostRepository.save(discussPost);
    }

    /**
     * 根据帖子id删除帖子
     * @param id 帖子id
     */
    public void deleteDiscussPost(int id) {
        discussPostRepository.deleteById(id);
    }

    /**
     * 根据关键词查询帖子
     * @param keyword   关键词
     * @param current   当前页码
     * @param limit     每页数据数量
     * @return  分页结果
     */
    public Page<DiscussPost> searchDiscussPost(String keyword, int current, int limit) {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))    // 构建搜索条件 多字段查询内容
                .withSorts(
                        SortBuilders.fieldSort("type").order(SortOrder.DESC), // 构建排序顺序 先按照type倒序排
                        SortBuilders.fieldSort("score").order(SortOrder.DESC), // 再按score倒序排
                        SortBuilders.fieldSort("createTime").order(SortOrder.DESC)  // 再按创建时间 倒序排
                )
                .withPageable(PageRequest.of(current, limit))    // 分页查询 第几页, 该页显示数据数量
                .withHighlightFields(
                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                )   // 配置字段高亮显示
                .build();
        SearchHits<DiscussPost> searchHits = restTemplate.search(searchQuery, DiscussPost.class);
        // SearchPage<DiscussPost> page = SearchHitSupport.searchPageFor(searchHits, searchQuery.getPageable());
        // 获取高亮结果集
        List<DiscussPost> list = new ArrayList<>();
        for (SearchHit<DiscussPost> searchHit : searchHits) {
            DiscussPost discussPost = searchHit.getContent();
            if (searchHit.getHighlightFields().get("title") != null) {
                discussPost.setTitle(searchHit.getHighlightFields().get("title").get(0));
                // discussPost.setContent(searchHit.getHighlightField("content").toString());
            }
            if (searchHit.getHighlightFields().get("content") != null) {
                discussPost.setContent(searchHit.getHighlightFields().get("content").get(0));
                // discussPost.setContent(searchHit.getHighlightField("content").toString());
            }
            list.add(discussPost);
        }
        // 组装分页对象
        // System.out.println(pageInfo.getTotalElements());    // 获取查询得到数据总数
        // System.out.println(pageInfo.getTotalPages());   // 获取总页数
        // System.out.println(pageInfo.getNumber());   // 获取当前页码
        // System.out.println(pageInfo.getSize());     // 获取当前页面个数
        // 输出分页结果
        return new PageImpl<>(list, searchQuery.getPageable(), searchHits.getTotalHits());
    }

}
